﻿using ServiceStack.Redis;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using Top.Common;
using Top.Data;
using Top.DataBase;
using Top.DataBase.Model;

namespace TopsNtegratingProcessingWindowsService
{
    partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
       }
        //private const string SingleHost = "localhost";
        private const string SingleHost = "8cf5c9b595894d8c.m.cnhza.kvstore.aliyuncs.com";
        private const int RedisPort = 6379;
        private const string RedisPwd = "8cf5c9b595894d8c:Tops4008125121";
        private const string ChannelName = "TopsHandleLuckRecordWindowsService";
        protected static object _lock = new object();//当前对象
        private Timer timer;
        protected override void OnStart(string[] args)
        {
            // TODO:  在此处添加代码以启动服务。   
            try
            {
                timer = new System.Timers.Timer();
                timer.Interval = 1000;
                //timer = new Timer(1000 * 10); //间隔10秒  
                timer.Enabled = true;
                timer.Elapsed += this.TimeOut;
                timer.Start();
            }
            catch (Exception ex)
            {
                ErrorLog.WriteLog("[自动处理兑换记录数据]服务报错：" + ex.Message);
            }
        }

        protected override void OnStop()
        {
            // TODO:  在此处添加代码以执行停止服务所需的关闭操作。
            timer.Close();
        }

        private void TimeOut(object sender, EventArgs e)
        {
            timer.Close();
            try
            {
                lock (_lock)
                {
                    RedisSub();
                }
            }
            catch (Exception ex)
            {
                ErrorLog.WriteLog("[自动处理兑换记录数据]服务报错：" + ex.Message);
            }
            finally
            {
                timer.Start();
            }
        }


        static void RedisSub()
        {
            try
            {
                using (var redisConsumer = new RedisClient(SingleHost, RedisPort, RedisPwd))
                //using (var redisConsumer = new RedisClient(SingleHost))
                using (var subscription = redisConsumer.CreateSubscription())
                {
                    subscription.OnMessage = (channel, msg) =>
                    {
                        Console.WriteLine(String.Format("{0}: {1}", channel, msg));
                        if (!string.IsNullOrWhiteSpace(msg))
                        {
                            Work(msg.Split('-').FirstOrDefault(), msg.Split('-').LastOrDefault());
                        }
                    };
                    subscription.SubscribeToChannels(ChannelName);
                }

            }
            catch (Exception ex)
            {
                ErrorLog.WriteLog(ex);
            }
        }

        static void Work(string luckRecordKid, string brokerKid)
        {
            #region 双11
            Dictionary<string, string> dicExchangeNotDisplay = new Dictionary<string, string>();
            dicExchangeNotDisplay.Add("1000积分", string.Empty);
            dicExchangeNotDisplay.Add("2000积分", string.Empty);
            dicExchangeNotDisplay.Add("3000积分", string.Empty);

            Dictionary<string, string> dicLuckRecordNotDisplay = new Dictionary<string, string>();
            dicLuckRecordNotDisplay.Add("谢谢参与", string.Empty);

            Dictionary<string, string> dicWinList = new Dictionary<string, string>();
            dicWinList.Add("销冠手机", string.Empty);
            dicWinList.Add("蓝牙耳机", string.Empty);
            dicWinList.Add("电暖气", string.Empty);
            dicWinList.Add("打火机", string.Empty);
            dicWinList.Add("1000积分", string.Empty);
            dicWinList.Add("2000积分", string.Empty);
            dicWinList.Add("3000积分", string.Empty);

            Dictionary<string, string> dicAutoList = new Dictionary<string, string>();
            dicAutoList.Add("1000积分", string.Empty);
            dicAutoList.Add("2000积分", string.Empty);
            dicAutoList.Add("3000积分", string.Empty);


            Dictionary<string, string> dicProductTipList = new Dictionary<string, string>();
            dicProductTipList.Add("销冠手机", string.Empty);
            dicProductTipList.Add("蓝牙耳机", string.Empty);
            dicProductTipList.Add("电暖气", string.Empty);
            dicProductTipList.Add("打火机", string.Empty);
            #endregion


            int userKid = Convert2.ToInt32(brokerKid, 0);
            int mode = userKid % 4;

            string tableName = "T_LuckRecord";
            switch (mode)
            {
                case 0:
                    tableName = "T_LuckRecord";
                    break;
                case 1:
                    tableName = "T_LuckRecord2";
                    break;
                case 2:
                    tableName = "T_LuckRecord3";
                    break;
                case 3:
                    tableName = "T_LuckRecord4";
                    break;
                default:
                    tableName = "T_LuckRecord";
                    break;
            }

            using (var db = new DbTour())
            {
                try
                {
                    #region 根据redis 订阅机制 获取中奖编号处理数据

                    string sqlLuckRecord = string.Format("select * from {0} where Kid={1} and and ExchangeKid=0", tableName, luckRecordKid);
                    T_LuckRecord item = db.Sql(sqlLuckRecord, luckRecordKid).FirstOrDefault<T_LuckRecord>().Result;
                    if (item == null)
                    {
                        ErrorLog.WriteLog(string.Format("纪录编号：{0},提示信息：{1}", luckRecordKid, "该记录不存在"));
                        return;
                    }

                    #region 处理业务

                    const string sqlLuckProduct = "select * from T_LuckProduct where Kid={0}";
                    T_LuckProduct luckProductModel = db.Sql(sqlLuckProduct, item.LuckProductKid).FirstOrDefault<T_LuckProduct>().Result;
                    if (luckProductModel == null)
                    {
                        ErrorLog.WriteLog(string.Format("抽中物品名称：{0},提示信息：{1}", luckProductModel.Name, "该记录不存在"));
                        return;
                    }

                    if (luckProductModel.Name == "谢谢参与")
                    {
                        ErrorLog.WriteLog(string.Format("纪录编号：{0}，抽中物品名称：{1}，提示信息：{2}", luckRecordKid, luckProductModel.Name, "不扣积分范畴"));
                        return;
                    }

                    const string sqlExchangeRule = "select * from T_ExchangeRule where F_ProductKid={0}";
                    T_ExchangeRule wxchangeRuleModel = db.Sql(sqlExchangeRule, item.LuckProductKid).FirstOrDefault<T_ExchangeRule>().Result;
                    if (wxchangeRuleModel == null)
                    {
                        ErrorLog.WriteLog(string.Format("兑换规则产品编号：{0},提示信息：{1}", item.LuckProductKid, "该记录不存在"));
                        return;
                    }

                    db.Begin();


                    if (UpdateLuckProduct(item.LuckProductKid??0, db) <= 0)
                    {
                        db.Rollback();
                        return;
                    }

                    //新增兑换记录信息
                    Guid guid = Guid.NewGuid();
                    var productsexchange = new T_ProductsExchange()
                    {
                        F_UserKid = item.BrokerKid,
                        F_ProductKid = item.LuckProductKid ?? 0,
                        F_ExchangeTime = DateTime.Now,
                        F_PointNum = -50,//抽奖积分
                        F_IsDisplay = dicExchangeNotDisplay.ContainsKey(luckProductModel.Name) ? 0 : 1,//1显示  0不显示
                        F_OrderNo = DateTime.Now.ToString("yyyyMMddHHmmfff"),
                        F_Guid = guid,
                        F_IsStatus = dicAutoList.ContainsKey(luckProductModel.Name) ? 10 : (wxchangeRuleModel.F_Status == 1 ? 1 : 3), //1:审核中 3：兑换成功
                        F_ExchangeType = "幸运大转盘"
                    };
                    int exchangeKid = ProductsExchange_Add(productsexchange, db);
                    if (exchangeKid <= 0)
                    {
                        db.Rollback();
                        return;
                    }


                    //更新中奖纪录中兑换记录编号
                    if (LuckRecord_Update(exchangeKid, item.Kid, db, tableName) <= 0)
                    {
                        db.Rollback();
                        return;
                    }


                    //抽奖扣积分
                    if (UpdateBrokerPoint(item.BrokerKid, -50, "broker.point.cash", db) <= 0)
                    {
                        db.Rollback();
                        return;
                    }


                    //抽中积分奖励
                    if (luckProductModel.Point > 0)
                    {
                        if (UpdateBrokerPoint(item.BrokerKid, luckProductModel.Point, "broker.pointluck.award", db) <= 0)
                        {
                            db.Rollback();
                            return;
                        }
                    }

                    #endregion

                    db.Commit();
                    return;

                    #endregion


                    #region foreach


                    //DateTime startDate = DateTime.Now.Date;
                    //DateTime endDate = startDate.AddDays(1);
                    //const string sqlLuckRecord = "select * from T_LuckRecord where ExchangeKid=0 and CreateTime>={0} and CreateTime<{1}";
                    //IList<T_LuckRecord> luckRecordList = db.Sql(sqlLuckRecord, startDate, endDate).ToList<T_LuckRecord>();
                    //foreach (var item in luckRecordList)
                    //{
                    //    #region MyRegion

                    //    const string sqlLuckProduct = "select * from T_LuckProduct where Kid={0}";
                    //    T_LuckProduct luckProductModel = db.Sql(sqlLuckProduct, item.LuckProductKid).FirstOrDefault<T_LuckProduct>();

                    //    if (dicLuckRecordNotDisplay.ContainsKey(luckProductModel.Name))
                    //    {
                    //        return;
                    //    }


                    //    const string sqlExchangeRule = "select * from T_ExchangeRule where F_ProductKid={0}";
                    //    T_ExchangeRule wxchangeRuleModel = db.Sql(sqlExchangeRule, item.LuckProductKid).FirstOrDefault<T_ExchangeRule>();

                    //    db.Begin();


                    //    //新增兑换记录信息
                    //    Guid guid = Guid.NewGuid();
                    //    var productsexchange = new T_ProductsExchange()
                    //    {
                    //        F_UserKid = item.BrokerKid,
                    //        F_ProductKid = item.LuckProductKid ?? 0,
                    //        F_ExchangeTime = DateTime.Now,
                    //        F_PointNum = -100,//抽奖积分
                    //        F_IsDisplay = dicExchangeNotDisplay.ContainsKey(luckProductModel.Name) ? 0 : 1,//1显示  0不显示
                    //        F_OrderNo = DateTime.Now.ToString("yyyyMMddHHmmfff"),
                    //        F_Guid = guid,
                    //        F_IsStatus = dicAutoList.ContainsKey(luckProductModel.Name) ? 10 : (wxchangeRuleModel.F_Status == 1 ? 1 : 3), //1:审核中 3：兑换成功
                    //        F_ExchangeType = "幸运大转盘"
                    //    };
                    //    int exchangeKid = ProductsExchange_Add(productsexchange, db);
                    //    if (exchangeKid <= 0)
                    //    {
                    //        db.Rollback();
                    //        return;
                    //    }


                    //    //更新中奖纪录中兑换记录编号
                    //    if (LuckRecord_Update(exchangeKid, item.Kid, db) <= 0)
                    //    {
                    //        db.Rollback();
                    //        return;
                    //    }


                    //    //抽奖扣积分
                    //    if (UpdateBrokerPoint(item.BrokerKid, -100, "broker.point.cash", db) <= 0)
                    //    {
                    //        db.Rollback();
                    //        return;
                    //    }


                    //    //抽中积分奖励
                    //    if (luckProductModel.Point > 0)
                    //    {
                    //        if (UpdateBrokerPoint(item.BrokerKid, luckProductModel.Point, "broker.pointluck.award", db) <= 0)
                    //        {
                    //            db.Rollback();
                    //            return;
                    //        }
                    //    }

                    //    #endregion

                    //    db.Commit();
                    //    return;
                    //}

                    #endregion

                }
                catch (Exception ex)
                {
                    db.Rollback();
                    ErrorLog.WriteLog(ex);
                    return;
                }
            }


        }

        public static int UpdateLuckProduct(int luckRecordKid, DbTour db)
        {

            const string sql = @"UPDATE [T_LuckProduct]
                                            SET [Count] = [Count] - 1
                        	                    ,[LuckCount] = [LuckCount] + 1
                                            WHERE Kid ={0}
                        	                    AND [Count] > 0
                        	                    AND [LuckCount] < [MaxCount]";

            return db.Sql(sql, luckRecordKid).ExecuteNonQuery().Result;
        }

        public static int UpdateBrokerPoint(int userKid, int point, string remark, DbTour db)
        {
            var brokerPoint = GetBrokerPoint(userKid, db);
            if (brokerPoint == null) return -1;

            brokerPoint.F_PointBalance += point;
            //TODO 积分更新有问题 待确认
            if (point > 0)
            {
                brokerPoint.F_PointAll += point;
            }
            if (point < 0)
            {
                brokerPoint.F_PointCash += -point;
            }
            PointManager_AddPoint(userKid, point, remark, db);
            return UpdateField(brokerPoint.Kid, brokerPoint.F_UserKid, brokerPoint.F_PointBalance, brokerPoint.F_PointCash, brokerPoint.F_PointAll, db);

        }

        internal static bool PointManager_AddPoint(int userKid, int point, string remark, DbTour db)
        {
            var brokerPoint = PointManager_Get(userKid, db);
            if (brokerPoint == null) return false;

            var pointDetail = new T_PointDetail()
            {
                F_AddTime = DateTime.Now,
                F_BuildingKid = 0,
                F_PointCode = remark,
                F_Point = point,
                F_PointSource = 4,
                F_PointId = brokerPoint.Kid
            };

            const string sql =
 @"insert into T_PointDetail ([F_PointId],[F_BuildingKid],[F_PointCode],[F_Point],[F_AddTime],[F_PointSource])
                values({0:F_PointId},
                {0:F_BuildingKid},
                {0:F_PointCode},
                {0:F_Point},
                {0:F_AddTime},
                {0:F_PointSource})
                select @@identity;";

            return db.Sql(sql, pointDetail).ExecuteScalar<int>().Result > 0;


        }

        public static T_PointMain PointManager_Get(int userKid, DbTour db)
        {
            const string sql = @"select top 1 * from T_PointMain where F_UserKid = {0} and F_UserType='T_Broker'";
            return db.Sql(sql, userKid).FirstOrDefault<T_PointMain>().Result;

        }

        private static int UpdateField(int pointMainKid, int userKid, int pointBalance, int pointCash, int pointAll, DbTour db)
        {
            var obj = new
            {
                F_PointBalance = pointBalance,
                F_PointCash = pointCash,
                F_UserKid = userKid,
                F_PointAll = pointAll
            };
            const string sql = @"update T_PointMain set F_PointBalance={0:F_PointBalance},F_PointCash={0:F_PointCash},F_PointAll={0:F_PointAll} where F_UserKid={0:F_UserKid}";
            return db.Sql(sql, obj).ExecuteNonQuery().Result;
        }

        public static T_PointMain GetBrokerPoint(int userKid, DbTour db)
        {
            const string sql = @"select top 1 * from T_PointMain where F_UserKid = {0} and F_UserType='T_Broker'";
            T_PointMain resultModel = db.Sql(sql, userKid).FirstOrDefault<T_PointMain>().Result;
            if (resultModel != null)
            {
                return resultModel;
            }
            return new T_PointMain();

        }

        public static int LuckRecord_Update(int exchangeKid, int luckRecordKid, DbTour db, string tableName)
        {
            string sql = string.Format("UPDATE {0} set ExchangeKid={1} where Kid={2}", tableName, exchangeKid, luckRecordKid);
            return db.Sql(sql).ExecuteNonQuery().Result;
        }

        public static int ProductsExchange_Add(T_ProductsExchange model, DbTour db)
        {
            const string sql = @"insert into T_ProductsExchange ([F_UserKid],[F_ProductKid],[F_ExchangeTime],[F_PointNum],[F_OrderNo],[F_Guid],[F_IsStatus],[F_Remark],[F_ExchangeType],[F_IsDisplay]) 
                values ({0:F_UserKid},
                        {0:F_ProductKid},
                        {0:F_ExchangeTime},
                        {0:F_PointNum},
                        {0:F_OrderNo},
                        {0:F_Guid},
                        {0:F_IsStatus},
                        '',
                        {0:F_ExchangeType},
                        {0:F_IsDisplay})
                select @@identity;";

            return db.Sql(sql, model).ExecuteScalar<int>().Result;
        }

        public class T_LuckProduct
        {
            /// <summary>
            /// 奖品id
            /// </summary>
            public int Kid { get; set; }
            /// <summary>
            /// 奖品图片角度
            /// </summary>
            public double Angle { get; set; }
            /// <summary>
            /// 奖品名称
            /// </summary>
            public string Name
            {
                get;
                set;
            }
            /// <summary>
            /// 中奖概率
            /// </summary>
            public int Chance { get; set; }
            /// <summary>
            /// 奖品数量
            /// </summary>
            public int Count { get; set; }
            /// <summary>
            /// 增加积分，实物为0，虚拟为对应的积分
            /// </summary>
            public int Point { get; set; }
            /// <summary>
            /// 中奖描述
            /// </summary>
            public string Description { get; set; }

            /// <summary>
            /// 出奖周期
            /// </summary>
            public int Rate { get; set; }

            /// <summary>
            /// 周期内最大出奖量
            /// </summary>
            public int MaxCount { get; set; }

            /// <summary>
            /// 周期内已出奖数量
            /// </summary>
            public int LuckCount { get; set; }

        }

    }

}
